package oc.tm.sg.core.rpc.provider;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import oc.tm.sg.core.conf.GovernConf;
import oc.tm.sg.core.monitor.MemoryCollectMonitor;
import oc.tm.sg.core.monitor.Monitor;
import oc.tm.sg.core.rpc.SgRpcProcessor;
import oc.tm.sg.core.rpc.annotation.Msg;
import oc.tm.sg.core.rpc.annotation.SPI;
import oc.tm.sg.core.rpc.annotation.support.Scans;
import oc.tm.sg.core.rpc.consumer.RpcConsumerFactory;
import oc.tm.sg.core.rpc.po.ScanResult;
import oc.tm.sg.core.rpc.po.ServicePo;
import oc.tm.sg.registry.common.Constants;
import oc.tm.sg.registry.common.URL;
import oc.tm.sg.registry.common.extension.ExtensionLoader;
import oc.tm.sg.registry.core.Registry;
import oc.tm.sg.registry.core.RegistryFactory;

import org.aeonbits.owner.ConfigFactory;
import org.zbus.kit.NetKit;
import org.zbus.kit.log.Logger;
import org.zbus.rpc.direct.Service;
import org.zbus.rpc.direct.ServiceConfig;

/**
 * RPC提供者工厂
 * @author lry
 */
public enum RpcProviderFactory {
	
	INSTANCE;
	private static final Logger logger=Logger.getLogger(RpcProviderFactory.class); 
	
	private Set<Object> modules=new HashSet<Object>();
	
	/**
	 * 配置信息
	 */
	private GovernConf governConf=null;
	
	//扫描服务
	private ScanResult scanResult;
	
	private ServiceConfig config=null;
	private Service svc=null;
	
	private RegistryFactory factory =null;
	private Registry registry =null;
	
	//监控器
	private Monitor monitor;
	private Monitor memoryMonitor;
	
	//////////getter/////////////////
	
	public Set<Object> getModules() {
		return modules;
	}
	public GovernConf getGovernConf() {
		return governConf;
	}
	public ScanResult getScanResult() {
		return scanResult;
	}
	public ServiceConfig getConfig() {
		return config;
	}
	public Service getSvc() {
		return svc;
	}
	public Monitor getMemoryMonitor() {
		return memoryMonitor;
	}

	/**
	 * 添加一个模块
	 * @param module
	 */
	public void addModule(Object module) {
		modules.add(module);
	}
	
	/**
	 * 添加多个模块
	 * @param modules
	 */
	public void addModules(Set<Object> modules) {
		this.modules=modules;
	}
	
	/**
	 * 初始化
	 */
	private void init(){
		try {
			governConf=ConfigFactory.create(GovernConf.class);
			
			//扫描服务
			this.scanResult=scan(governConf.scan());
			for (Class<?> impl:scanResult.getServiceImplSet()) {
				try {
					Object module=impl.newInstance();
					this.modules.add(module);
				} catch (InstantiationException | IllegalAccessException e) {
					if(logger.isDebugEnabled()){
						logger.debug("Failed when the "+impl+" was to be an instance, because "+impl+" did not have a default constructor.");
					}
				}
			}
		} catch (Throwable t) {
			logger.error("Init Provider is failed!");
			t.printStackTrace();
		}
	}

	/**
	 * 启动服务提供者
	 */
	public void start(Integer port) {
		ServiceConfig config = new ServiceConfig(); 
		config.serverPort = port;
		
		start(config);
	}
	
	/**
	 * 启动服务提供者
	 * @param config
	 */
	public void start(ServiceConfig conf) {
		if(logger.isInfoEnabled()){
			logger.info("Startting Provider,please waitting...");
		}
		
		this.config=conf;

		//初始化
		init();
		
		try {
			SgRpcProcessor processor = new SgRpcProcessor(); 
			if(modules!=null){
				for (Object module:modules) {
					processor.addModule(module);
					if(logger.isInfoEnabled()){
						logger.info("Add module is:"+module);
					}
				}
			}
			config.messageProcessor = processor; 
			
			svc = new Service(config);
			svc.start(); 
			
			if(logger.isInfoEnabled()){
				logger.info("Started Provider is successed!");
			}
			
			factory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
	    	registry = factory.getRegistry(URL.valueOf(governConf.registryURL()));
	    	
	    	if(registry.isAvailable()){
	    		//发布开放的所有服务
	    		for (ServicePo sPo:scanResult.getServicePoSet()) {
	    			Map<String, String> regsitryParameters=new HashMap<String, String>();
	    			regsitryParameters.put(Constants.APPLICATION_KEY, governConf.application());//所属应用
	    			regsitryParameters.put(Constants.GROUP_KEY, sPo.getGroup());//服务分组
	    			regsitryParameters.put(Constants.VERSION_KEY, sPo.getVersion());//版本号
	    			regsitryParameters.put(oc.tm.sg.core.Constants.OWNER_KEY, sPo.getOwner());//负责人
	    			regsitryParameters.put(oc.tm.sg.core.Constants.ORGANIZATION_KEY, sPo.getOrganization());//负责人所属组织
	    			regsitryParameters.put(Constants.METHOD_KEY, sPo.getMethod());//暴露的方法
	    			regsitryParameters.put(Constants.WEIGHT_KEY, String.valueOf(sPo.getWeight()));//权重:默认为100
	    			regsitryParameters.put(oc.tm.sg.core.Constants.STAT_KEY, String.valueOf(sPo.getStat()));//服务使用状态:默认为“正常”,否则为“禁用”
	    			regsitryParameters.put(oc.tm.sg.core.Constants.TITLE_KEY, sPo.getTitle());//标题
	    			regsitryParameters.put(oc.tm.sg.core.Constants.MSG_KEY, sPo.getMsg());//说明信息
	    			
	    			URL url=new URL(oc.tm.sg.core.Constants.DEFAULT_PROTOCOL, NetKit.getLocalIp(), conf.serverPort, sPo.getService(), regsitryParameters);
	    			
	    			//发布服务
					registry.register(url);
				}
	    		
	    		if(governConf.monitorSwitch()){
	    			//启动消费者
		    		RpcConsumerFactory.INSTANCE.start();
		    		//消费监控服务
					monitor=RpcConsumerFactory.INSTANCE.getService(Monitor.class);
					//创建内存收集器，并注入远程调度服务监控 
					memoryMonitor=new MemoryCollectMonitor(monitor);
	    		}else{
	    			if(logger.isDebugEnabled()){
						logger.debug("Monitor switch is closed!");
					}
	    		}
	    	}else{
	    		if(logger.isDebugEnabled()){
					logger.debug("Registry is UnAvailable!");
				}
	    	}
		} catch (Throwable t) {
			logger.info("Started Provider is failed!");
			t.printStackTrace();
		}
	}
	
	/**
	 * 销毁
	 */
	public void destroy() {
		if(logger.isInfoEnabled()){
			logger.info("Closing Provider, please waitting...");
		}
		try{
			if(svc!=null){
				svc.close();
			}
			
			if(governConf.monitorSwitch()){//销毁消费者
				RpcConsumerFactory.INSTANCE.destroy();
			}
			
			if(logger.isInfoEnabled()){
				logger.info("Closed Provider is successed!");
			}
		} catch (Throwable t) {
			logger.info("Closed Provider is failed!");
			t.printStackTrace();
		}
	}
	
	/**
	 * 扫描开放的服务
	 * @param pack
	 * @return [interface,impl,service]
	 */
	public static ScanResult scan(String pack) {
		Set<Class<?>> serviceImplSet=new HashSet<Class<?>>();//服务实现类
		Set<ServicePo> servicePoSet=new HashSet<ServicePo>();//服务配置
		Map<String,ServicePo> serviceMap=new LinkedHashMap<String,ServicePo>();//服务[配置,接口实现类]
		
		Set<Class<?>> classList = Scans.scans(pack);
		for (Class<?> clazz : classList) {
			SPI spi = clazz.getAnnotation(SPI.class);
			if (spi != null) {// 筛选服务接口
				Class<?>[] interfs = clazz.getInterfaces();// 获取类实现的所有接口
				if(interfs!=null){
					if(interfs.length>0){
						serviceImplSet.add(clazz);
					}
				}
				for (Class<?> interf : interfs) {
					if (interf.getName().equals("java.io.Serializable")) {
						continue;
					}
					
					ServicePo service=new ServicePo();
					service.setGroup(spi.group());//接口所属分组
					service.setVersion(spi.version());//版本号
					service.setOwner(spi.owner());//负责人
					service.setOrganization(spi.organization());//所属组织
					service.setService(interf.getName());//服务接口
					
					//获取接口开放的服务方法
					String method_str="";
					Method[] methods=interf.getMethods();
					for (Method method:methods) {
						method_str+=method.getName()+Constants.COMMA_SEPARATOR;
					}
					//去掉末尾的分隔符
					if(method_str.length()>0&&method_str.endsWith(Constants.COMMA_SEPARATOR)){
						method_str=method_str.substring(0,method_str.length()-1);
					}
					service.setMethod(method_str);//开放的方法集合
					
					//可选注解
					Msg msg = clazz.getAnnotation(Msg.class);
					if(msg!=null){
						service.setTitle(msg.value());//接口方法
						service.setMsg(msg.msg());//接口说明						
					}
					
					//收集
					servicePoSet.add(service);
					serviceMap.put(interf.getName(),service);
				}
			}
		}
		return new ScanResult(serviceImplSet, servicePoSet, serviceMap);
	}
}
